<!-- VirtualList.vue -->
<template>
    <div class="virtual-list" ref="listContainer" @scroll="onScroll">
        <div class="virtual-list-content" :style="{ height: totalHeight + 'px' }">
            <div v-for="(item, index) in visibleItems" :key="item.id"
                :style="{ height: itemHeight + 'px', transform: `translateY(${offsetY}px)` }" class="virtual-list-item">
                <slot :item="item" :index="index"></slot>
            </div>
        </div>
    </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue';

const props = defineProps({
    items: {
        type: Array,
        required: true,
    },
    itemHeight: {
        type: Number,
        default: 30,
    },
    itemComponent: {
        type: Object,
        required: true,
    },
});

const listContainer = ref(null);
const startIndex = ref(0);
const visibleCount = ref(0);
const offsetY = ref(0);
const totalHeight = computed(() => props.items.length * props.itemHeight);

const calculateVisibleCount = () => {
    const container = listContainer.value;
    if (container) {
        const containerHeight = container.clientHeight;
        visibleCount.value = Math.ceil(containerHeight / props.itemHeight) + 1;
    }
};

const visibleItems = computed(() => {
    const endIndex = startIndex.value + visibleCount.value;
    return props.items.slice(startIndex.value, endIndex);
});

const onScroll = () => {
    const container = listContainer.value;
    if (container) {
        const scrollTop = container.scrollTop;
        startIndex.value = Math.floor(scrollTop / props.itemHeight);
        offsetY.value = scrollTop - (scrollTop % props.itemHeight);
    }
};

onMounted(() => {
    calculateVisibleCount();
    window.addEventListener('resize', calculateVisibleCount);
});

onUnmounted(() => {
    window.removeEventListener('resize', calculateVisibleCount);
});
</script>

<style scoped>
.virtual-list {
    overflow-y: auto;
    height: 400px;
    /* 设定固定高度 */
    border: 1px solid #ddd;
    position: relative;
}

.virtual-list-content {
    position: relative;
}

.virtual-list-item {
    box-sizing: border-box;
    border-bottom: 1px solid #f0f0f0;
    line-height: 30px;
    /* 与 itemHeight 相同 */
    padding: 0 10px;
}
</style>